package com.cg.leetcode;

import org.junit.Test;

import java.util.Arrays;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 622.设计循环队列
 *
 * @program: LeetCode->LeetCode_622
 * @description: 622.设计循环队列
 * @author: cg
 * @create: 2021-09-06 10:07
 **/
public class LeetCode_622 {

    @Test
    public void test622() {
        MyCircularQueue circularQueue = new MyCircularQueue(3);
        System.out.println(circularQueue.enQueue(1));
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.Front());
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.enQueue(2));
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.enQueue(3));
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.enQueue(4));
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.Rear());
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.isFull());
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.deQueue());
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.enQueue(4));
        System.out.println(circularQueue.toString());
        System.out.println(circularQueue.Rear());
        System.out.println(circularQueue.toString());
        circularQueue.deQueue();
        circularQueue.deQueue();
        circularQueue.deQueue();
        System.out.println(circularQueue);
        System.out.println(circularQueue.Front());
        System.out.println(circularQueue);
    }

    /**
     * 设计你的循环队列实现。 循环队列是一种线性数据结构，其操作表现基于 FIFO（先进先出）原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
     * <p>
     * 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里，一旦一个队列满了，我们就不能插入下一个元素，即使在队列前面仍有空间。但是使用循环队列，我们能使用这些空间去存储新的值。
     * <p>
     * 你的实现应该支持如下操作：
     * 1) MyCircularQueue(k): 构造器，设置队列长度为 k 。
     * 2) Front: 从队首获取元素。如果队列为空，返回 -1 。
     * 3) Rear: 获取队尾元素。如果队列为空，返回 -1 。
     * 4) enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
     * 5) deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
     * 6) isEmpty(): 检查循环队列是否为空。
     * 7) isFull(): 检查循环队列是否已满。
     * <p>
     * 示例
     * MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
     * circularQueue.enQueue(1);  // 返回 true
     * circularQueue.enQueue(2);  // 返回 true
     * circularQueue.enQueue(3);  // 返回 true
     * circularQueue.enQueue(4);  // 返回 false，队列已满
     * circularQueue.Rear();  // 返回 3
     * circularQueue.isFull();  // 返回 true
     * circularQueue.deQueue();  // 返回 true
     * circularQueue.enQueue(4);  // 返回 true
     * circularQueue.Rear();  // 返回 4
     * <p>
     * 提示：
     * 1) 所有的值都在 0 至 1000 的范围内；
     * 2) 操作数将在 1 至 1000 的范围内；
     * 3) 请不要使用内置的队列库。
     */
    /*class MyCircularQueue {
        private final int[] queue;
        private int maxSize;
        private int front;
        private int rear;

        public MyCircularQueue(int k) {
            maxSize = k+1;
            queue = new int[maxSize];
            front = 0;
            rear = 0;
        }

        public boolean enQueue(int value) {
            if (isFull()) {
                return false;
            }
            rear = (rear + 1) % maxSize;
            queue[rear] = value;
            return true;
        }

        public boolean deQueue() {
            if (isEmpty()) {
                return false;
            }
            front = (front + 1) % maxSize;
            return true;
        }

        public int Front() {
            if (isEmpty()) {
                return -1;
            }
            return queue[(front + 1) % maxSize];
        }

        public int Rear() {
            if (isEmpty()) {
                return -1;
            }
            return queue[(front + getCount()) % maxSize];
        }

        public boolean isEmpty() {
            return rear == front;
        }

        public boolean isFull() {
            return (rear + 1) % maxSize == front;
        }

        public int getCount() {
            return (rear - front + maxSize) % maxSize;
        }

        @Override
        public String toString() {
            return "MyCircularQueue{" +
                    "queue=" + Arrays.toString(queue) +
                    ", max_size=" + maxSize +
                    ", front=" + front +
                    ", rear=" + rear +
                    ", count=" + getCount() +
                    '}';
        }
    }*/

    class MyCircularQueue {

        private int[] queue;
        private int headIndex;
        private int count;
        private int capacity;

        /** Initialize your data structure here. Set the size of the queue to be k. */
        public MyCircularQueue(int k) {
            this.capacity = k;
            this.queue = new int[k];
            this.headIndex = 0;
            this.count = 0;
        }

        /** Insert an element into the circular queue. Return true if the operation is successful. */
        public boolean enQueue(int value) {
            if (this.count == this.capacity) {
                return false;
            }
            this.queue[(this.headIndex + this.count) % this.capacity] = value;
            this.count += 1;
            return true;
        }

        /** Delete an element from the circular queue. Return true if the operation is successful. */
        public boolean deQueue() {
            if (this.count == 0) {
                return false;
            }
            this.headIndex = (this.headIndex + 1) % this.capacity;
            this.count -= 1;
            return true;
        }

        /** Get the front item from the queue. */
        public int Front() {
            if (this.count == 0)
                return -1;
            return this.queue[this.headIndex];
        }

        /** Get the last item from the queue. */
        public int Rear() {
            if (this.count == 0)
                return -1;
            int tailIndex = (this.headIndex + this.count - 1) % this.capacity;
            return this.queue[tailIndex];
        }

        /** Checks whether the circular queue is empty or not. */
        public boolean isEmpty() {
            return (this.count == 0);
        }

        /** Checks whether the circular queue is full or not. */
        public boolean isFull() {
            return (this.count == this.capacity);
        }
    }

    /*class MyCircularQueue {

        private ListNode head, tail;
        private int count;
        private int capacity;

        // Initialize your data structure here. Set the size of the queue to be k.
        public MyCircularQueue(int k) {
            this.capacity = k;
        }

        // Insert an element into the circular queue. Return true if the operation is successful.
        public boolean enQueue(int value) {
            if (this.count == this.capacity) {
                return false;
            }

            ListNode newNode = new ListNode(value);
            if (this.count == 0) {
                head = tail = newNode;
            } else {
                tail.next = newNode;
                tail = newNode;
            }
            this.count += 1;
            return true;
        }

        // Delete an element from the circular queue. Return true if the operation is successful.
        public boolean deQueue() {
            if (this.count == 0) {
                return false;
            }
            this.head = this.head.next;
            this.count -= 1;
            return true;
        }

        // Get the front item from the queue.
        public int Front() {
            if (this.count == 0) {
                return -1;
            } else {
                return this.head.val;
            }
        }

        // Get the last item from the queue.
        public int Rear() {
            if (this.count == 0) {
                return -1;
            } else {
                return this.tail.val;
            }
        }

        // Checks whether the circular queue is empty or not.
        public boolean isEmpty() {
            return (this.count == 0);
        }

        // Checks whether the circular queue is full or not.
        public boolean isFull() {
            return (this.count == this.capacity);
        }
    }*/

}
